/*
 * This work is free software;
 * you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2.
 * This work is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the version 2 of the GNU General Public License for more details.
 */

package be.c4j.maven.plugins;

import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;

import java.util.List;

/**
 * Goal which checks dependency version conflicts.
 *
 * @goal dependency-check
 * @phase process-sources
 */
public class DependencyCheckMojo extends AbstractMojo {

    /**
     * The maven project.
     *
     * @parameter expression="${project}"
     * @readonly
     */
    private MavenProject project;

    public void execute() throws MojoExecutionException {
        List<Dependency> managedDependencies = project.getDependencyManagement().getDependencies();
        List<Dependency> dependencies = project.getDependencies();
        if (dependencyConflict(dependencies, managedDependencies)) {
            //throw new MojoExecutionException("There is a dependency management issue.");
        }

    }

    private boolean dependencyConflict(List<Dependency> someDependencies, List<Dependency> someManagedDependencies) {
        boolean result = false;
        Dependency matchedDependency;
        for (Dependency dependency : someDependencies) {
            matchedDependency = matchDependency(dependency, someManagedDependencies);
            if (hasDifferentVersions(dependency, matchedDependency)) {
                logDifference(dependency, matchedDependency);
                result = true;
            }
        }
        return result;
    }

    private Dependency matchDependency(Dependency someDependency, List<Dependency> someManagedDependencies) {
        Dependency result = null;

        for (Dependency dependency : someManagedDependencies) {
            if (matchDependency(dependency, someDependency)) {
                result = dependency;
            }
            if (result != null) {
                break;
            }
        }
        return result;

    }

    private boolean matchDependency(Dependency dependency1, Dependency dependency2) {
        boolean result = true;
        if (!dependency1.getGroupId().equals(dependency2.getGroupId())) {
            result = false;
        }
        if (result && !dependency1.getArtifactId().equals(dependency2.getArtifactId())) {
            result = false;
        }
        if (result && !dependency1.getType().equals(dependency2.getType())) {
            result = false;
        }

        if (result) {
            String classifier1 = dependency1.getClassifier();
            String classifier2 = dependency2.getClassifier();
            if ((classifier1 == null) ^ (classifier2 == null)) {
                result = false;
            }
            if (result && classifier1 != null && classifier2 != null) {
               result = classifier1.equals(classifier2);
            }
        }
        return result;
    }

    private boolean hasDifferentVersions(Dependency dependency1, Dependency dependency2) {
        return !dependency1.getVersion().equals(dependency2.getVersion());
    }

    private void logDifference(Dependency someDependency, Dependency someMatchedDependency) {
        StringBuilder message = new StringBuilder();
        message.append("There is a version mismatch between a Managed dependency and a dependency\n");
        message.append("Managed dependency : ").append(someMatchedDependency.toString()).append("\n");
        message.append("Dependency : ").append(someDependency.toString()).append("\n");

        getLog().error(message.toString());
    }
}
